/*
 *  BullyAI.cpp
 *  RiskAI
 *
 *  Created by Chris on 11/15/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "BullyAI.h"

#include <iostream>
#include <vector>

using namespace std;

//**********************************************************************************
//				CONSTRUCTION/DESTRUCTION
//**********************************************************************************

CBullyAI::CBullyAI(int iIndex, CBoard* pxBoard)
	: CPlayer(iIndex, pxBoard)
{
}





//**********************************************************************************
//				VIRTUAL FUNCTIONS
//**********************************************************************************

int
CBullyAI::PickTerritory(vector<int> viAvailables)
{
	// Choose randomly
	unsigned int iIndex = rand() % viAvailables.size();
	return viAvailables[iIndex];
}

//==================================================================================

int
CBullyAI::AssignTroops(int iNumTroops)
{
	// figure out which territory borders weakest enemy that doesn't have enough
	// troops to launch an attack (enemy + 2)
	int iWeakestForce = INFINITY;
	int iWeakestEnemy = -1;
	
	for(unsigned int i=0; i<m_viTerritories.size(); i++)
	{
		int iTerritory = m_viTerritories[i];
		int iEnemies = StrengthOfWeaskestEnemy(iTerritory);
		int iTroops = m_pxBoard->GetTerritory(iTerritory)->GetNumArmies() - 1;
		if(iTroops <= iEnemies + 1 && iEnemies < iWeakestForce)
		{
			iWeakestForce = iEnemies;
			iWeakestEnemy = iTerritory;
		}
	}
	
	if(iWeakestEnemy != -1) return iWeakestEnemy;
	
	
	// If I have a troop surplus, all border territories might think they
	// have "enough".  In this case just distribute randomly to borders.
	vector<int> viBorders;
	for(unsigned int i=0; i<m_viTerritories.size(); i++)
	{
		int iEnemies = StrengthOfWeaskestEnemy(m_viTerritories[i]);
		if(iEnemies != INFINITY)
			viBorders.push_back(m_viTerritories[i]);
	}
	
	int iNumBorders = int(viBorders.size());
	return viBorders[rand() % iNumBorders];
}

//==================================================================================

int
CBullyAI::MoveTroops(int iSourceIndex, int iDestinationIndex)
{
	// Only keep whatever troops here that I need to attack more neighbors
	int iSourceEnemies = StrengthOfWeaskestEnemy(iSourceIndex);
	int iSourceTroops = m_pxBoard->GetTerritory(iSourceIndex)->GetNumArmies();
	
	if(iSourceEnemies > 0) iSourceEnemies += 2;
	
	return max(0, iSourceTroops - iSourceEnemies);
}

//==================================================================================

RiskAction
CBullyAI::DecideOnAction(vector<int> viViableAttackers)
{
	// cycle through attack options
	for(unsigned int i=0; i<viViableAttackers.size(); i++)
	{
		int iAttacker = viViableAttackers[i];
		int iTroops = m_pxBoard->GetTerritory(iAttacker)->GetNumArmies();
		
		// find weakest bordering enemy
		int iWeakestForce = INFINITY;
		int iWeakestEnemy;
		vector<int> viBorders = m_pxBoard->GetTerritory(iAttacker)->GetBorderIndices();
		for(unsigned int j=0; j<viBorders.size(); j++)
		{
			int iEnemy = viBorders[j];
			int iOwner = m_pxBoard->GetTerritory(iEnemy)->GetOwner();
			int iEnemies = m_pxBoard->GetTerritory(iEnemy)->GetNumArmies();
			if(iEnemies < iWeakestForce && iOwner != m_iIndex)
			{
				iWeakestEnemy = iEnemy;
				iWeakestForce = iEnemies;
			}
		}
		
		// attack it if I have more troops than him
		if(iWeakestForce < iTroops)
		{
			int iDice = min(3, iTroops - 1);
			return RiskAction(iAttacker, iWeakestEnemy, iDice);
		}
		
	}
	
	return END_TURN;
}

//==================================================================================

int
CBullyAI::PickDefendingDie(int* aiAttackDice, int iTarget)
{
	int iMaxDice = min(2, m_pxBoard->GetTerritory(iTarget)->GetNumArmies());
	
	return (aiAttackDice[1] > 4 ? 1 : iMaxDice);
}

//==================================================================================

CFortification
CBullyAI::FortifyTroops(vector<int> viFortifiers)
{
	// find fortification that would put the most troops next to the
	// weakest enemy (none is a viable option as well)
	int iGlobalWeakestEnemies = INFINITY;
	CFortification xBestFort = NO_FORTIFICATION;
	
	for(unsigned int i=0; i<viFortifiers.size(); i++)
	{
		int iWeakestForce = INFINITY;
		int iWeakestEnemy;
		
		int iMe = viFortifiers[i];
		vector<int> viPossibles = m_pxBoard->GetTerritory(iMe)->GetBorderIndices();
		viPossibles.push_back(iMe);
		
		for(unsigned int j=0; j<viPossibles.size(); j++)
		{
			int iEnemies = StrengthOfWeaskestEnemy(viPossibles[j]);
			if(iEnemies < iWeakestForce)
			{
				iWeakestForce = iEnemies;
				iWeakestEnemy = viPossibles[j];
			}
		}
		
		if(iWeakestEnemy != iMe && iWeakestForce < iGlobalWeakestEnemies)
		{
			iGlobalWeakestEnemies = iWeakestForce;
			int iTroops = m_pxBoard->GetTerritory(iMe)->GetNumArmies() - 1;
			xBestFort = CFortification(iMe, iWeakestEnemy, iTroops);
		}
	}
	
	return xBestFort;
}